﻿using MiniFox.Components;
using MiniFox.Infrastructure;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MiniFox.Tasks
{
    /// <summary>
    /// 任务单元
    /// </summary>
    public class TaskItem : Component
    {
        TaskAction[] _taskActions;
        TaskScheduler _taskScheduler;
        Thread _thread;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="taskScheduler"></param>
        /// <param name="taskActions"></param>
        public TaskItem(string name, TaskScheduler taskScheduler, TaskAction[] taskActions)
        {
            this.Name = name;
            _taskScheduler = taskScheduler;
            _taskActions = taskActions;
            _thread = new Thread(this.ProcessTask);
        }
        /// <summary>
        /// 
        /// </summary>
        public TaskAction[] TaskActions
        {
            get
            {
                return _taskActions;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        protected virtual TaskScheduler Scheduler
        {
            get { return _taskScheduler; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DurationUnit DurationUnit
        {
            get { return Scheduler.DurationUnit; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DateTime? ScheduledStartTime
        {
            get { return this.Scheduler.StartTime; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DateTime? ScheduledEndTime
        {
            get { return this.Scheduler.EndTime; }
        }
        /// <summary>
        /// 下一次执行时间
        /// </summary>
        public DateTime? NextExecuteTime
        {
            get { return this.Scheduler.NextExecuteTime; }
        }
        /// <summary>
        /// 
        /// </summary>
        public TaskStatus ExecuteStatus
        {
            get;
            internal set;
        }

        /// <summary>
        /// 停止任务
        /// </summary>
        internal void Stop()
        {
            if (this.ExecuteStatus == TaskStatus.WaitingForStop)
                return;

            this._thread.Abort();
            this.Scheduler.initialize();
            this.ExecuteStatus = TaskStatus.Stopped;
            Logging(TaskEventType.任务停止, "任务停止");
        }

        /// <summary>
        /// 执行任务
        /// </summary>
        internal void Start()
        {

            if (this.ExecuteStatus == TaskStatus.WaitingForStop)
                return;


            bool startImmidate = this.ScheduledStartTime == null || this.ScheduledStartTime <= DateTime.Now;
            this.ExecuteStatus = TaskStatus.Started;
            Logging(TaskEventType.任务启动, $"任务启动, 计划开始时间:{(startImmidate ? "立即执行" : this.ScheduledStartTime.ToString())}\t 计划中止时间为:{(this.ScheduledEndTime == null ? "无" : this.ScheduledEndTime.ToString())}");

            if (!startImmidate)//等待任务开始执行
            {
                Logging(TaskEventType.任务等待执行, $"正在等待执行，执行时间为{this.ScheduledStartTime}");
                this.ExecuteStatus = TaskStatus.WaitingForProcess;
                TimeSpan? span = (this.ScheduledStartTime - DateTime.Now);
                Thread.Sleep(span.GetValueOrDefault());
            }

            this._thread.Start();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="eventType"></param>
        /// <param name="description"></param>
        protected virtual void Logging(TaskEventType eventType, string description)
        {
            try
            {
                var loggedDate = DateTime.Now;
                string txtlog = $"任务名称:{this.Name}\t事件类型: {eventType}\t事件描述: {description}\t发生时间: {loggedDate}";
            
                this.WriteInfoLog(txtlog);
                #if DEBUG
                Debug.WriteLine(txtlog);
                #endif
            }
            catch
            {
            }

        }

        internal void ProcessTask()
        {
            try
            {

                do
                {
                    Logging(TaskEventType.任务执行中, "任务执行中");
                    this.ExecuteStatus = TaskStatus.InProgress;
                    foreach (TaskAction action in this.TaskActions)
                    {
                        try
                        {
                            Logging(TaskEventType.任务执行开始, $"Action[{action.Name}]执行开始");
                            action.Execute();
                            Logging(TaskEventType.任务执行结束, $"Action[{action.Name}]执行结束");
                        }
                        catch (Exception e)
                        {
                            Logging(TaskEventType.任务执行异常, $"Action[{action.Name}]产生异常：{e}");
                            if (this.Scheduler.StopOnError)
                                break;
                        }
                    }

                    //强制回收后休眠
                    GC.Collect();

                    if (this.Scheduler.ScheduleType == ScheduleType.Iteration)
                    {
                        this.Scheduler.SetNextExecute();
                        if (this.ScheduledEndTime != null && this.NextExecuteTime >= this.ScheduledEndTime)//等待任务结束
                        {
                            Logging(TaskEventType.任务等待停止, $"正在等待停止，计划结束时间为 {this.ScheduledEndTime}");
                            TimeSpan? span = (this.ScheduledEndTime - DateTime.Now);
                            this.ExecuteStatus = TaskStatus.WaitingForStop;
                            if (span.GetValueOrDefault().Ticks > 0)
                                Thread.Sleep(span.GetValueOrDefault());//等待退出时间
                            break;
                        }
                        else//等待任务下一次执行
                        {
                            Logging(TaskEventType.任务等待执行, $"正在等待下一次执行，下一次执行时间为 {this.NextExecuteTime}");
                            this.ExecuteStatus = TaskStatus.WaitingForNext;
                            TimeSpan? span = (this.NextExecuteTime - DateTime.Now);
                            if (span.GetValueOrDefault().Ticks > 0)
                                Thread.Sleep(span.GetValueOrDefault());
                        }
                    }

                }
                while (this.Scheduler.ScheduleType == ScheduleType.Iteration);

                Stop();
            }
            catch (Exception e)
            {
                Logging(TaskEventType.任务停止, $"任务运行过程中出现异常，意外中止，异常信息:{e.Message}\n\r异常源:{e.StackTrace}");
            }
        }
    }
}
